home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr09 / vstsrc.zip / RTD.C < prev    next >
C/C++ Source or Header  |  1995-01-28  |  27KB  |  891 lines

  1. /*
  2.  * %W% %E% %U%  [EXTREL_1.2]
  3.  *
  4.  * VersaTrack orbit calculations are based on those that appear in Dr. Manfred
  5.  * Bester's sattrack program (the Unix(tm) versions 1 and 2).
  6.  *
  7.  * The data from which the maps where generated come from "xsat", an
  8.  * X-Windows program by David A. Curry (N9MSW).
  9.  *
  10.  * Site coordinates come from various sources, including a couple of
  11.  * World Almanacs, and also from both of the programs mentioned above.
  12.  *
  13.  * The following are authors' applicable copyright notices:
  14.  *
  15.  *                                                                               
  16.  * Copyright (c) 1992, 1993, 1994 Manfred Bester. All Rights Reserved.        
  17.  *                                                                           
  18.  * Permission to use, copy, modify, and distribute this software and its      
  19.  * documentation for educational, research and non-profit purposes, without   
  20.  * fee, and without a written agreement is hereby granted, provided that the  
  21.  * above copyright notice and the following three paragraphs appear in all    
  22.  * copies.                                                                    
  23.  *                                                                              
  24.  * Permission to incorporate this software into commercial products may be    
  25.  * obtained from the author, Dr. Manfred Bester, 1636 M. L. King Jr. Way,     
  26.  * Berkeley, CA 94709, USA.                                                   
  27.  *                                                                             
  28.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,  
  29.  * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF    
  30.  * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED   
  31.  * OF THE POSSIBILITY OF SUCH DAMAGE.                                         
  32.  *                                                                             
  33.  * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT       
  34.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A    
  35.  * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"       
  36.  * BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,  
  37.  * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.                                   
  38.  *                                                                             
  39.  *                                                                             
  40.  * Copyright 1992 by David A. Curry                                            
  41.  *                                                                             
  42.  * Permission to use, copy, modify, distribute, and sell this software and its 
  43.  * documentation for any purpose is hereby granted without fee, provided that  
  44.  * the above copyright notice appear in all copies and that both that copyright
  45.  * notice and this permission notice appear in supporting documentation.  The  
  46.  * author makes no representations about the suitability of this software for  
  47.  * any purpose.  It is provided "as is" without express or implied warranty.   
  48.  *                                                                             
  49.  * David A. Curry, N9MSW                                                       
  50.  * Purdue University                                                           
  51.  * Engineering Computer Network                                                
  52.  * 1285 Electrical Engineering Building                                        
  53.  * West Lafayette, IN 47907                                                    
  54.  * davy@ecn.purdue.edu                                                         
  55.  *                                                                             
  56.  * VersaTrack Copyright (c) 1993, 1994 Siamack Navabpour. All Rights Reserved.
  57.  *
  58.  * Permission is hereby granted to copy, modify and distribute VersaTrack
  59.  * in whole, or in part, for educational, non-profit and non-commercial use
  60.  * only, free of charge or obligation, and without agreement, provided that
  61.  * all copyrights and restrictions noted herein are observed and followed, and
  62.  * additionally, that this and all other copyright notices listed herein
  63.  * appear unaltered in all copies and in all derived work.
  64.  *
  65.  * This notice shall not in any way void or superceed any of the other authors
  66.  * rights or privilages.
  67.  *
  68.  * VersaTrack IS PRESENTED FREE AND "AS IS", WITHOUT ANY WARRANTY OR SUPPORT.
  69.  * YOU USE IT AT YOUR OWN RISK. The author(s) shall not be liable for any
  70.  * direct, indirect, incidental, or consequential damage, loss of profits or
  71.  * other tangible or intangible losses or benefits, arising out of or related
  72.  * to its use. VersaTrack carries no warranty, explicit or implied, including
  73.  * but not limited to those of merchantability and fitness for a particular
  74.  * purpose.
  75.  *
  76.  * Siamack Navabpour, 12342 Hunter's Chase Dr. Apt. 2114, Austin, TX 78729.
  77.  * sia@bga.com or sia@realtime.com.
  78.  */
  79.  
  80.  
  81. #include <windows.h>
  82. #include <math.h>
  83. #include <stdio.h>
  84. #include <stdlib.h>
  85.  
  86. #include "resource.h"
  87. #include "vstdefs.h"
  88. #include "vsttype.h"
  89. #include "vstextrn.h"
  90.  
  91.  
  92. static short itemid[] = {
  93.     IDC_RTD_TIME,      IDC_RTD_AZIMUTH,
  94.     IDC_RTD_ELEVATION, IDC_RTD_RANGE,
  95.     IDC_RTD_DOPPLER,   IDC_RTD_PATHLOSS,
  96.     IDC_RTD_LATITUDE,  IDC_RTD_LONGITUDE,
  97.     IDC_RTD_HEIGHT,    IDC_RTD_VISIBILITY,
  98.     IDC_RTD_PHASE,     IDC_RTD_SQUINT,
  99.     IDC_RTD_TMODE
  100. };
  101.  
  102. #undef  NITEMS
  103. #define NITEMS  (sizeof(itemid) / sizeof(itemid[0]))
  104.  
  105.  
  106. void
  107. convcoord(lat, lon, x, y)
  108. double lat, lon;
  109. int *x,*y;
  110. {
  111.     lon = -lon - mapdata.m_minx;
  112.     lat = -lat - mapdata.m_miny;
  113.  
  114.     *x = (int) (lon * ScaleX);
  115.     *y = (int) (lat * ScaleY) + ytop;
  116. }
  117.  
  118.  
  119. void
  120. rtd_update(sp)
  121. select_t *sp;
  122. {
  123.     track_t *tp;
  124.     result_t *rp;
  125.     int x, y;
  126.     int inview;
  127.     char *itemp;
  128.     double ttime;
  129.  
  130.     if (!sp)
  131.         return;
  132.  
  133.     tp = sp->sl_tp;
  134.     rp = sp->sl_rp;
  135.  
  136.     if (sp->flags & SE_RTD_SIM) {
  137.         sp->simtime += tp->steptime;
  138.         ttime = sp->simtime;
  139.     }
  140.     else
  141.         ttime = utctime();
  142.  
  143.     rtd_lock(sp);
  144.     if (predict(modelflag, sp, ttime) == 0) {
  145.         rtd_unlock(sp);
  146.         rtd_finish(sp);
  147.         return;
  148.     }
  149.     convcoord(rp->r_lat, rp->r_long, &x, &y);
  150.  
  151.     sp->satx = x;
  152.     sp->saty = y;
  153.  
  154.     if (sp->first) {
  155.         sp->dsatx = sp->satx;
  156.         sp->dsaty = sp->saty;
  157.     }
  158.     
  159.     if (!sp->rtdhwnd || (sp->flags & SE_RTD_SIM)) {
  160.         rtd_unlock(sp);
  161.         return;
  162.     }    
  163.  
  164.     rtd_unlock(sp);
  165.  
  166.     itemp = sp->sl_itemp;
  167.        inview  = rp->r_elevation > tp->minelevation;
  168.     rp->r_viswarn = 0;
  169.     timeStr(rp->r_time, tp->sitep, sp->flags, 0, itemp+(0*20));
  170.     sprintf(itemp+( 1*20), "%-3.1lf",  rp->r_azimuth);
  171.     sprintf(itemp+( 2*20), "%-+2.1lf", rp->r_elevation);
  172.     sprintf(itemp+( 3*20), "%-.1lf", (sp->flags & SE_RTD_KM) ? rp->r_range :
  173.         rp->r_range / 1.6);
  174.     sprintf(itemp+( 4*20), "%-05d", (int)(rp->r_doppler+0.5));
  175.     sprintf(itemp+( 5*20), "%-.1lf", rp->r_pathloss);
  176.     sprintf(itemp+( 6*20), "%-.1lf %c", fabs(rp->r_lat), (rp->r_lat > 0) ? 'N' : 'S');
  177.     sprintf(itemp+( 7*20), "%-.1lf %c", fabs(rp->r_long), (rp->r_long > 0) ? 'W' : 'E');
  178.     sprintf(itemp+( 8*20), "%-.1lf", (sp->flags & SE_RTD_KM ) ?
  179.         rp->r_height : rp->r_height / 1.6);
  180.     itemp[9*20] = rp->r_insun;
  181.     itemp[9*20+1] = 0;
  182.     sprintf(itemp+(10*20), "%03d", rp->r_phase);
  183.     if (tp->satp->s_flags & SF_ATTITUDE)
  184.         sprintf(itemp+(11*20), "%.1lf", rp->r_squint);
  185.     else
  186.         strcpy(itemp+(11*20), "N/A");
  187.     sprintf(itemp+(12*20),"%-3.3s",rp->r_modestr);
  188.     strcpy (itemp+13*20, inview ? "Visible" : "               ");
  189.  
  190.     if (sp->first) {
  191.            sprintf(itemp+(14*20), "%-.31s, %-.39s", tp->sitep->c_name,
  192.                tp->sitep->c_locale );
  193.         itemp[14*20 - 1] = 0;
  194.         strncpy(itemp+(16*20), tp->satp->s_name, 19);
  195.     }
  196.     PostMessage(sp->rtdhwnd, RTD_UPDATE, (WPARAM) 0, (LPARAM) sp);
  197. }
  198.  
  199. int
  200. rtd_start(hwnd, hinst, sp)
  201. HWND hwnd;
  202. HANDLE hinst;
  203. select_t *sp;
  204. {
  205.     int rtd_task_id, error;
  206.     extern DWORD rtd_display_thread(select_t *);
  207.     extern char *ErrorString(int);
  208.     track_t *tp;
  209.     double ttime;
  210.     
  211.     if (!sp)
  212.         return TRUE;
  213.         
  214.     rtd_lock(sp);
  215.     if (sp->rtdhwnd || sp->running || sp->terminate) {
  216.         rtd_unlock(sp);
  217. #ifdef _DEBUG_
  218.        diag("rtd still active: hwnd %x  run %d  term %d  thhandle %x\n",
  219.             sp->rtdhwnd, sp->running, sp->terminate, sp->rtd_thread_handle);
  220. #endif /* _DEBUG_ */
  221.         return TRUE;
  222.     }
  223.     tp = sp->sl_tp;
  224.     if (!tp->sitep || !tp->satp) {
  225.         rtd_unlock(sp);
  226.         return TRUE;
  227.     }
  228.     ttime = utctime();
  229.  
  230.     if (sp->flags & SE_RTD_SIM) {
  231.         if (tp->starttime != -1.0)
  232.             sp->simtime = ttime = tp->starttime;
  233.         else
  234.             sp->simtime = ttime;
  235.     }
  236.  
  237.     predict_init(modelflag, sp,  ttime);
  238.     
  239.     sp->first = 1;
  240.     sp->timerid = 0;
  241.     sp->timeron = 0;
  242.     sp->ticks = 0;
  243.     sp->flags &= ~(SE_THSTOP | SE_THSTOPPED);
  244.         
  245.     sp->rtdhwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_RTD), Gwnd, RTDisplayProc);
  246.     error = GetLastError();
  247.     if ((sp->rtdhwnd == NULL) || (sp->rtdhwnd == INVALID_HANDLE_VALUE)) {
  248.         sp->rtdhwnd = NULL;
  249.         rtd_unlock(sp);
  250.         sprintf(tmpbuf,"cannot create rtd dlg window: %s",
  251.             ErrorString(error));
  252.         usermsg(tmpbuf);
  253.         return FALSE;
  254.     }
  255.     SetWindowLong(sp->rtdhwnd, DWL_USER, (LONG) sp);
  256.     SetClassLong(sp->rtdhwnd, GCL_HICON,
  257.         (long) LoadIcon(hinst, MAKEINTRESOURCE(IDI_RTDICON)));
  258.  
  259.     sp->rtd_thread_handle = CreateThread(NULL, 0,
  260.         (PTHREAD_START_ROUTINE) rtd_display_thread,  (LPVOID) sp,
  261.         CREATE_SUSPENDED, &rtd_task_id);
  262.     
  263.     error = GetLastError();
  264.     if ((sp->rtd_thread_handle == NULL) ||
  265.         (sp->rtd_thread_handle == INVALID_HANDLE_VALUE)) {
  266.         sp->rtd_thread_handle = NULL;
  267.         DestroyWindow(sp->rtdhwnd);
  268.         rtd_unlock(sp);
  269.         sprintf(tmpbuf, "Cannot create display thread for satellite: %s",
  270.             ErrorString(error));
  271.         usermsg(tmpbuf);
  272.         return FALSE;
  273.     }
  274.     rtd_unlock(sp);
  275.     ResumeThread(sp->rtd_thread_handle);
  276.     return TRUE;
  277. }
  278.  
  279. BOOL
  280. rtd_finish(sp)
  281. select_t *sp;
  282. {
  283.     BOOL r = FALSE;
  284.  
  285.     if (!sp)
  286.         return r;
  287.  
  288.     rtd_lock(sp);
  289.     if (sp->running) {
  290.         sp->terminate = 1;
  291.         r = TRUE;
  292.     }
  293.  
  294.     if (sp->rtdhwnd) {
  295.         rtd_unlock(sp);
  296.         DestroyWindow(sp->rtdhwnd);
  297.         r = TRUE;
  298.     }
  299.     else
  300.         rtd_unlock(sp);
  301.  
  302.     return r;
  303. }
  304.  
  305.  
  306. BOOL CALLBACK RTDisplayProc(hwnd, message, wParam, lParam)
  307. HWND hwnd;
  308. UINT message;
  309. WPARAM wParam;
  310. LPARAM lParam;
  311. {
  312.     int i, iconic;
  313.     POINT *p;
  314.     select_t *sp;
  315.     char *itemp;
  316.     
  317.     sp = (select_t *) GetWindowLong(hwnd, DWL_USER);
  318.             
  319.     switch (message) {
  320.  
  321.     case WM_INITDIALOG:
  322.         p = DialogPos(Gwnd, hwnd);
  323.         EnableWindow(hwnd, TRUE);
  324.         SetWindowPos(hwnd, 0, (int)p->x, (int)p->y, 0, 0,
  325.             SWP_NOZORDER | SWP_NOSIZE);
  326.         return TRUE;
  327.  
  328.     case RTD_UPDATE:
  329.         sp = (select_t *) lParam;
  330.         ASSERT(sp);
  331.         itemp = sp->sl_itemp;
  332.  
  333.         iconic = IsIconic(hwnd);
  334.  
  335.         if (i = sp->first) {
  336.             sp->first = 0;
  337.             SetWindowText(hwnd, itemp+(16*20));
  338.             if (sp->flags & SE_RTD_UTC)
  339.                 SendDlgItemMessage(hwnd, IDC_RTD0, WM_SETTEXT, (WPARAM)0,
  340.                     (LPARAM) "Time          ");
  341.             else if (sp->flags & SE_RTD_SLT)
  342.                 SendDlgItemMessage(hwnd, IDC_RTD0, WM_SETTEXT, (WPARAM)0,
  343.                     (LPARAM) "Site Time");                   
  344.  
  345.             SendDlgItemMessage(hwnd, IDC_RTD_OBSERVED,
  346.                 (UINT)WM_SETTEXT, (WPARAM) 0, (LPARAM) (itemp+(14*20)));
  347.  
  348.             if (sp->flags & (SE_RTD_DIC|SE_RTD_HIC)) {
  349.                 if (sp->flags & SE_RTD_HIC)
  350.                     ShowWindow(hwnd, SW_HIDE);
  351.                 ShowWindow(hwnd, SW_SHOWMINIMIZED);
  352.                 iconic = TRUE;
  353.             }
  354.             else {
  355.                 OpenIcon(hwnd);
  356.                 ShowWindow(hwnd, SW_SHOW);
  357.                 iconic = FALSE;
  358.             }
  359.             PostMessage(Gwnd, RTD_WRUNNING, (WPARAM)0, (LPARAM) hwnd);
  360.         }
  361.  
  362.         if (!iconic || i)
  363.             for (i=0; i<NITEMS; i++)
  364.                 SendDlgItemMessage(hwnd, itemid[i],
  365.                      (UINT)WM_SETTEXT, (WPARAM)0, (LPARAM) (itemp+(i*20)));
  366.  
  367.         if (itemp[13*20] != ' ') {
  368.             if (sp->timeron == (char)0) {
  369.                 
  370.                 if ((sp->flags & (SE_RTD_BEEP|SE_RTD_SIM)) == SE_RTD_BEEP)
  371.                     SendMessage(Gwnd, RTD_LONGBEEPUP, (WPARAM)0, (LPARAM) 0);
  372.  
  373.                 if ((sp->flags & SE_RTD_POA) && iconic) {
  374.                     OpenIcon(hwnd);
  375.                     if (sp->flags & SE_RTD_HIC)
  376.                         ShowWindow(hwnd, SW_SHOW);
  377.                     sp->flags |= SE_RTD_ICONIC; /* we opened it */
  378.                 }
  379.                 sp->ticks = 0;
  380.                 i = 0;
  381.                 iconic = (sp->sl_rp->r_rising) ? 613 : 890; 
  382.                 do {
  383.                     sp->timerid = IDT_RTDBASE + sp->sl_index + i;
  384.                     i++;
  385.                   
  386.                 } while (!SetTimer(hwnd, (UINT) sp->timerid, (DWORD) iconic, (TIMERPROC)NULL));
  387.                 sp->timeron = (char )1;
  388.             }
  389.         }
  390.         else {
  391.           if (sp->timeron) {
  392.             
  393.             KillTimer(hwnd, sp->timerid);
  394.             sp->timeron = (char )0;
  395.  
  396. #ifdef BLINKICON
  397.             ShowWindow(hwnd, iconic ? SW_SHOWMINIMIZED : SW_SHOW);
  398. #endif
  399.             SetWindowText(hwnd, itemp+(16*20));
  400.             SendDlgItemMessage(hwnd, IDC_RTD_INVIEW, WM_SETTEXT,
  401.                 (WPARAM) 0, (LPARAM)"                      ");
  402.  
  403.             if ((sp->flags & (SE_RTD_BEEP|SE_RTD_SIM)) == SE_RTD_BEEP)
  404.                 SendMessage(Gwnd, RTD_LONGBEEPDOWN, (WPARAM)0, (LPARAM) 0);
  405.  
  406.             if (!iconic && (sp->flags & SE_RTD_ICONIC)) {
  407.                 if (sp->flags & (SE_RTD_DIC | SE_RTD_HIC)) {
  408.                     if (sp->flags & SE_RTD_HIC)
  409.                         ShowWindow(hwnd, SW_HIDE);
  410.                     CloseWindow(hwnd);
  411.                 }
  412.             }
  413.             sp->flags &= ~SE_RTD_ICONIC;
  414.           }
  415.         }
  416.         return TRUE;
  417.  
  418.     case WM_SIZE:
  419.         if (!sp)
  420.             break;
  421.  
  422.         if ((sp->flags & SE_STATE) && !IsIconic(hwnd)) {
  423.             if (sp->flags & SE_WNDISICON) {
  424.                 if (sp->flags & SE_RTD_HIC)
  425.                     ShowWindow(hwnd, SW_HIDE);
  426.                 CloseWindow(hwnd);
  427.             }
  428.             else if (IsIconic(hwnd)) {
  429.                 if (sp->flags & SE_RTD_HIC)
  430.                     ShowWindow(hwnd, SW_SHOW);
  431.                 OpenIcon(hwnd);
  432.             }
  433.             sp->flags &= ~SE_STATE;
  434.             return TRUE;
  435.         }
  436.         if (!IsIconic(hwnd) && sp)
  437.             rtd_update(sp);
  438.         else if (sp && (sp->flags & SE_RTD_HIC))
  439.             ShowWindow(hwnd, SW_HIDE);
  440.         break;
  441.         
  442.    case WM_DESTROY:
  443.         if (InSendMessage())
  444.             ReplyMessage(TRUE);
  445.             
  446.         if (sp->timeron) {
  447.             KillTimer(hwnd, sp->timerid);
  448.             sp->timeron = (char) 0;
  449.         }
  450.         SendMessage(Gwnd, (UINT) RTD_WINEXIT, (WPARAM) 0, (LPARAM) sp);
  451.         Sleep(0);
  452.         break;
  453.  
  454.     case WM_TIMER:
  455.         itemp = sp->sl_itemp;
  456.  
  457.         if (sp->timeron && LOWORD(wParam) == sp->timerid) {
  458.             sp->ticks++;
  459.  
  460.             if (!IsIconic(hwnd)) {
  461.                 SetWindowText(hwnd, itemp+(16*20));
  462.                 SendDlgItemMessage(hwnd, IDC_RTD_INVIEW,
  463.                     (UINT) WM_SETTEXT, (WPARAM) 0, (sp->ticks & 1) ?
  464.                     (LPARAM) "            " : (LPARAM) "Visible" );
  465.             }
  466.             else if ((sp->flags & (SE_RTD_BOA|SE_RTD_SIM)) == SE_RTD_BOA)
  467. #ifdef BLINKICON
  468.                 ShowWindow(hwnd, (sp->ticks & 1) ? SW_HIDE : SW_SHOWMINIMIZED);
  469. #else
  470.                 SetWindowText(hwnd, (sp->ticks & 1) ? itemp+(16*20) :
  471.                         sp->sl_tp->sitep->c_name);
  472. #endif
  473.  
  474.             return TRUE;
  475.         }
  476.         break;
  477.  
  478.     case WM_COMMAND:
  479.         if (InSendMessage())
  480.             ReplyMessage(TRUE);
  481.  
  482.         if (LOWORD(wParam) == IDOK) {
  483.             if (sp->timeron) {
  484.                 KillTimer(hwnd, sp->timerid);
  485.                 sp->timeron = (char )0;
  486.             }
  487.             rtd_finish(sp);
  488.             return TRUE;
  489.         }
  490.         break;
  491.         
  492.     case WM_CLOSE:
  493.         if (sp->timeron) {
  494.             KillTimer(hwnd, sp->timerid);
  495.             sp->timeron = (char )0;
  496.         }
  497.         break;
  498.  
  499.     case RTD_TOGGLE_ICON:
  500.         ASSERT(sp);
  501.         if (IsIconic(hwnd)) {
  502.             OpenIcon(hwnd);
  503.             if (sp && (sp->flags & SE_RTD_HIC))
  504.                 ShowWindow(hwnd, SW_SHOW);
  505.             rtd_update(sp);
  506.         }
  507.         else {
  508.             if (sp && (sp->flags & SE_RTD_HIC))
  509.                 ShowWindow(hwnd, SW_HIDE);
  510.             CloseWindow(hwnd);
  511.         }
  512.         break;
  513.  
  514.     case WM_CTLCOLORDLG:
  515.     case WM_CTLCOLORSTATIC:
  516.         ColorSet(wParam, CWHITE, 7);     /* was 5=dark magenta, is 6=dark cyan */
  517.         return (BOOL) hDrawBrush[7];     /* text color was 8 = light grey */
  518.  
  519.     case WM_CTLCOLOREDIT:
  520.         ColorSet(wParam, CBLACK, 8);
  521.         return (BOOL) hDrawBrush[8];
  522.     }
  523.     return FALSE;
  524. }
  525.  
  526. static BOOL
  527. rtd_wantstop(select_t *sp)
  528. {
  529.     return sp->terminate != 0;
  530. }
  531.  
  532.  
  533. static void
  534. DrawSat(x, y, name)
  535. int x, y;
  536. char *name;
  537. {
  538.     RECT r;
  539.     SIZE sz;
  540. #define CRADIUS 4
  541.     display_lock();
  542.  
  543.     Ellipse(hCompatDC, x - CRADIUS, y - CRADIUS, x + CRADIUS, y + CRADIUS);
  544.  
  545.     DrawTextStr(hCompatDC, x + 5, y - 9, SRCINVERT, TextColor, CBLACK, hArial, name, &sz);
  546.  
  547.     r.left = x - CRADIUS - 1 ;
  548.     r.right = r.left + 14 + sz.cx;
  549.     r.top = y - 10;
  550.     r.bottom = r.top + MAX(14, sz.cy);
  551.     RedrawScreen(&r);
  552.     
  553.     display_unlock();
  554. }
  555.  
  556. static void setdx(select_t *sp) { sp->dsatx = sp->satx; }
  557. static int  getdx(select_t *sp) { return sp->dsatx; }
  558. static int  getx(select_t *sp) { return sp->satx; }
  559. static void setdy(select_t *sp) { sp->dsaty = sp->saty; }
  560. static int  getdy(select_t *sp) { return sp->dsaty; }
  561. static int  gety(select_t *sp) { return sp->saty; }
  562.  
  563. /*
  564.  * The thread used to display a satellite on the map. For each and every
  565.  * satellite/site pair one of these is created. As long as we have memory
  566.  * and cpu juice, why not!
  567.  *
  568.  * It is essential to use locks when updating the display bitmap, otherwise
  569.  * all sorts of hell will break loose. Hence, all those lock() and unlock()'s.
  570.  */
  571.  
  572. static DWORD
  573. rtd_display_thread(sp)
  574. register select_t *sp;
  575. {
  576.     int count,ticks;
  577.     BOOL pflag;
  578.     track_t *tp;
  579.     satellite_t *satp;
  580.     int updatecount,rs;
  581.     
  582.     ASSERT(!sp->running);
  583.     ASSERT(!sp->terminate);
  584.  
  585.     rtd_lock(sp);    
  586.     if (sp->running) {
  587.         rtd_unlock(sp);
  588.         ExitThread(0);
  589.     }
  590.     sp->running = 1;
  591.     sp->terminate = 0;
  592.     rtd_unlock(sp);
  593.  
  594.     pflag = FALSE;
  595.     tp = sp->sl_tp;
  596.     satp = tp->satp;
  597.  
  598.     sat_lock();
  599.     if (!(satp->s_flags & SF_DISP))
  600.         satp->s_flags |= SF_DISP;
  601.     else
  602.         satp = NULL;
  603.     sat_unlock();
  604.     
  605.     if (sp->flags & SE_RTD_SIM) {
  606.         rs = 100;
  607.         updatecount = 1;
  608.     }
  609.     else {
  610.         rs = RTD_SLEEPTIME;
  611.         updatecount = (int) ((float) (sp->updatetime * 1000) / (float) rs + 0.5) ;
  612.     }
  613.     GdiSetBatchLimit(1);
  614.     Sleep(((rand() >> 3) & 15) << 4);
  615.     PostMessage(Gwnd, RTD_TRUNNING, (WPARAM)0, (LPARAM) sp);
  616.     Sleep(20);
  617.     
  618.     for (count=updatecount, ticks=0; ; ticks++) {
  619.         if (++count >= updatecount) {
  620.             count = 0;
  621.             rtd_update(sp);
  622.         }
  623.  
  624.         rtd_lock(sp);
  625.         if (rtd_wantstop(sp)) {
  626.             rtd_unlock(sp);
  627.             break;
  628.         }
  629.         /*
  630.          * the SE_THSTOP flag is set when the user wants to re-draw the
  631.          * map while the thread is running. We'll freeze (i.e., suspend the
  632.          * thread) until the map is re-drawn, and then resume in a fresh
  633.          * state pretending that we haven't drawn the satellite on the map
  634.          * yet.
  635.          */
  636.         if (sp->flags & SE_THSTOP) {
  637.             sp->flags |= SE_THSTOPPED;
  638.             rtd_unlock(sp);
  639.  
  640.             PostMessage(Gwnd, RTD_STOPPED, (WPARAM) 0, (LPARAM) sp);
  641.             SuspendThread(sp->rtd_thread_handle);
  642.             Sleep(0); /* give up time slice just in case suspend thread doesn't
  643.                          take effect immediately. */
  644.  
  645.             rtd_lock(sp);
  646.             sp->flags &= ~SE_THSTOPPED;
  647.             rtd_unlock(sp);
  648.  
  649.             sp->first = 1;
  650.             rtd_update(sp);
  651.             pflag = FALSE; /* we did all that for this */
  652.         }
  653.         else
  654.             rtd_unlock(sp);
  655.  
  656.         if (satp) {
  657.             if (sp->flags & SE_RTD_BMP) {
  658.                 DrawSat(getdx(sp), getdy(sp), tp->satp->s_name);
  659.                 pflag = !pflag;
  660.             }
  661.             else {
  662.                 if (!pflag) {
  663.                     DrawSat(getdx(sp), getdy(sp), tp->satp->s_name);
  664.                     pflag = TRUE;
  665.                 }
  666.             }
  667.         }
  668.         else
  669.             pflag = TRUE;
  670.  
  671.         if (satp && pflag && ((getdx(sp) != getx(sp)) || (getdy(sp) != gety(sp)))) {
  672.             if (sp->flags & SE_RTD_BMP)
  673.                 Sleep((DWORD)rs);
  674.             DrawSat(getdx(sp), getdy(sp), tp->satp->s_name);
  675.             rtd_lock(sp);
  676.             setdx(sp);
  677.             setdy(sp);
  678.             rtd_unlock(sp);
  679.             pflag = !pflag;
  680.         }
  681.         if (sp->flags & SE_RTD_BMP || pflag)
  682.             Sleep((DWORD)rs);
  683.  
  684.         if (!satp && (ticks > 25)) {
  685.             ticks = 0;
  686.             satp = tp->satp;
  687.             sat_lock();
  688.             if (!(satp->s_flags & SF_DISP)) {
  689.                 satp->s_flags |= SF_DISP;
  690.                 pflag = FALSE;
  691.             }
  692.             else
  693.                 satp = NULL;
  694.             sat_unlock();
  695.         }
  696.     }
  697.     ASSERT(sp->running);        
  698.     ASSERT(sp->terminate);
  699.     Sleep(100);
  700.  
  701.     if (satp && pflag) {
  702.         DrawSat(getdx(sp), getdy(sp), tp->satp->s_name);
  703.     }
  704.     if (satp) {
  705.         sat_lock();
  706.         satp->s_flags &= ~SF_DISP;
  707.         sat_unlock();
  708.     }
  709.  
  710. #ifdef _DEBUG_
  711.     if (sp->terminate)
  712.         diag("thread %x by cmd, window handle %x\n",
  713.             sp->rtd_thread_handle, sp->rtdhwnd);
  714. #endif /* _DEBUG_ */
  715.  
  716.     rtd_lock(sp);
  717.  
  718. #if 0
  719.     sp->running = 0;
  720.     sp->terminate = 0;
  721.     sp->rtd_thread_handle = NULL;
  722. #endif    
  723.  
  724.     if (sp->rtdhwnd) {
  725.         rtd_unlock(sp);
  726.         DestroyWindow(sp->rtdhwnd);
  727.     }
  728.     else
  729.         rtd_unlock(sp);
  730.  
  731.     Sleep(0);
  732.     PostMessage(Gwnd, RTD_THDEXIT, (WPARAM) 0, (LPARAM) sp);
  733.     Sleep(50);
  734.     ExitThread((DWORD) 0);
  735.     return 0;
  736. }
  737.  
  738. BOOL
  739. rtd_anythread()
  740. {
  741.     select_t *sp;
  742.     int n;
  743.     
  744.     for (n = 0, sp = selInfo; sp; sp = sp->sl_next) {
  745.         rtd_lock(sp);
  746.         if (sp->running || sp->terminate || sp->rtdhwnd)
  747.             n++;
  748.         rtd_unlock(sp);
  749.     }
  750.     return n ? TRUE : FALSE;
  751. }
  752.  
  753. BOOL
  754. rtd_allstopped()
  755. {
  756.     select_t *sp;
  757.     int n;
  758.  
  759.     for (n = 0, sp = selInfo; sp; sp = sp->sl_next) {
  760.         rtd_lock(sp);
  761.         if (sp->running && !(sp->flags & SE_THSTOPPED) && (sp->flags & SE_THSTOP))
  762.                 n++;
  763.         rtd_unlock(sp);
  764.     }
  765.     return n ? FALSE : TRUE;
  766. }
  767.  
  768. void
  769. rtd_allstop()
  770. {
  771.     select_t *sp;
  772.  
  773.     for (sp = selInfo; sp; sp = sp->sl_next) {
  774.         rtd_lock(sp);
  775.         if (sp->running) {
  776.             if (!(sp->flags & SE_THSTOPPED) && !(sp->flags & SE_THSTOP) ) {
  777.                 sp->flags &= ~SE_THSTOPPED;
  778.                 sp->flags |= SE_THSTOP;
  779.             }
  780.         }
  781.         rtd_unlock(sp);
  782.     }
  783. }
  784.  
  785. BOOL
  786. rtd_allrunning()
  787. {
  788.     select_t *sp;
  789.     int n;
  790.     
  791.     for (n = 0, sp = selInfo; sp; sp = sp->sl_next) {
  792.         rtd_lock(sp);
  793.         if (sp->running && !sp->terminate && sp->rtdhwnd && !(sp->flags & SE_THSTOPPED)) {
  794.             rtd_unlock(sp);
  795.             continue;
  796.         }
  797.         rtd_unlock(sp);
  798.         return FALSE;
  799.     }
  800.     return TRUE;
  801. }
  802.  
  803. void
  804. rtd_allresume()
  805. {
  806.     select_t *sp;
  807.     int i;
  808.  
  809.     for (i=0,sp = selInfo; sp ; sp = sp->sl_next, i++) {
  810.         rtd_lock(sp);
  811.         if (sp->running && (sp->flags & SE_THSTOPPED)) {
  812.             rtd_unlock(sp);
  813.             ResumeThread(sp->rtd_thread_handle);
  814.         }
  815.         else
  816.             rtd_unlock(sp);
  817.     }
  818. }
  819.  
  820. void
  821. rtd_savewindowstate() /* called when the main window is being minimized */
  822. {
  823.     select_t *sp;
  824.     int i;
  825.  
  826.     for (i=0,sp = selInfo; sp ; sp = sp->sl_next, i++) {
  827.         rtd_lock(sp);
  828.         if (sp->running && sp->rtdhwnd)
  829.             sp->flags |= SE_STATE;
  830.             if (IsIconic(sp->rtdhwnd))
  831.                 sp->flags |= SE_WNDISICON;
  832.             else
  833.                 sp->flags &= ~SE_WNDISICON;
  834.         rtd_unlock(sp);
  835.     }
  836. }
  837.  
  838.  
  839. #ifdef _DEBUG_
  840. void
  841. thdump(flag)
  842. int flag;
  843. {
  844.     select_t * sp;
  845.     int i;
  846.     extern int debugflag;
  847.     
  848.     debugflag = 1;
  849.     for (i=0, sp = selInfo; sp; sp = sp->sl_next,i++) {
  850.         diag("%02d  R=%d  T=%d  T=%08x  W=%08x  F=%08x\n",
  851.             i, sp->running, sp->terminate, sp->rtd_thread_handle,
  852.             sp->rtdhwnd, sp->flags & (SE_THSTOP|SE_THSTOPPED));
  853.     }
  854.     debugflag = 0;
  855. }        
  856. #endif /* _DEBUG_ */
  857.  
  858. select_t *
  859. checksat(x, y) /* see if mouse cursor is near one of the satellites on the map*/
  860. int x,y;
  861. {
  862.     RECT r;
  863.     POINT p;
  864.     select_t *sp;
  865.     
  866.     p.x = x;
  867.     p.y = y;
  868.  
  869.     for (sp = selInfo; sp; sp = sp->sl_next) {
  870.         rtd_lock(sp);
  871.         if (sp->running && sp->rtdhwnd) {
  872.             r.left = sp->dsatx - 10;
  873.             r.right = sp->dsatx + 10;
  874.             r.top =  sp->dsaty - 10;
  875.             r.bottom = sp->dsaty + 10;
  876.             rtd_unlock(sp);
  877.             if (PtInRect(&r, p)) {
  878.                 if ((sp != currentSel) && ((serverInfo[0].srv_state == ST_SRV_RUNNING) ||
  879.                     (serverInfo[1].srv_state == ST_SRV_RUNNING)))
  880.                     if (!yesno("Radio/Rotator Control running. Are you sure you \
  881. want to change the current satellite ?"))
  882.                         return NULL;
  883.                 return currentSel = sp;
  884.             }
  885.         }
  886.         else
  887.             rtd_unlock(sp);
  888.     }
  889.     return NULL;
  890. }
  891.